﻿package bdz.controls {
	import bdz.common.events.NetStreamManagerEvent;
	import bdz.common.managers.NetStreamManager;
	import bdz.extensions.youtube.events.*;
	import bdz.extensions.youtube.ui.YTChromelessPlayer;
	
	import flash.display.*;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.utils.*;
	
	import gs.*;
	import gs.easing.*;
	
	/**
	 * ...
	 * @author Donald
	 */
	public class VideoController extends MovieClip {
		private var _ns:NetStreamManager;
		private var _playButton:MovieClip;
		private var _pauseButton:MovieClip;
		private var _loadBar:MovieClip;
		private var _playBar:MovieClip;
		private var _scrubber:MovieClip;
		private var _baseBar:MovieClip;
		private var _timeText:TextField;
		private var _volume:MovieClip;
		private var _fullscreen:MovieClip;
		private var _normalscreen:MovieClip;
		private var _scrubbing:Boolean = false;
		private var _volscrubber:MovieClip;
		private var _baseFrame:MovieClip;
		private var _max:Number;
		private var _playcompleted:Boolean = false;
		private var _vframe:MovieClip;
		private var _vbase:MovieClip;
		private var _vprogress:MovieClip;
		private var _volcontrol:MovieClip;
		private var _hasvolume:Boolean = true;
		private var _hasfullscreen:Boolean = true;
		private var _autoHideVolume:Boolean = true;
		private var _ytchromeless:Boolean = false;
		private var _ytstream:YTChromelessPlayer;
		private var _fstimer:Timer = new Timer(2000, 0);
		private var _hidden:Boolean = false;
		private var _autoHideControls:Boolean = false;
		
		public var defControlHeight:Number;
		
		function VideoController() {
			
			addEventListener(Event.ADDED_TO_STAGE, initializeComponent);
		}
		private function initializeComponent(evt:Event):void {
			
			assignReferences();
			initializeElements();
			_fstimer.addEventListener(TimerEvent.TIMER, onFSTimerTick);	
		}
		private function resetHideTimer(evt:MouseEvent):void {
			if (_hidden) {
				showMe();
				_fstimer.stop();
				_fstimer.start();
			}
		}
		private function onFSTimerTick(evt:TimerEvent):void {
			_fstimer.stop();
			if (!_hidden) {
				hideMe();
			}
		}
		private function showMe():void {
			_hidden = false;
			TweenMax.killTweensOf(this);
			TweenMax.to(this, 1, { alpha:1, ease:Strong.easeOut } );
		}
		private function hideMe():void {
			_hidden = true;
			TweenMax.killTweensOf(this);
			TweenMax.to(this, 1, { alpha:0, ease:Strong.easeOut } );
		}
		private function assignReferences():void {
			_playButton = this["play_button"];
			_pauseButton = this["pause_button"];
			_loadBar = this["load_progress"];
			_baseBar = this["base_marker"];
			_playBar = this["play_progress"];
			_scrubber = this["scrubber"];
			_timeText = this["time_text"];
			_volume = this["volume"];
			_fullscreen = this["fullscreen"];
			_volscrubber = this["volcontrol"].vscrubber;
			_vbase = this["volcontrol"].vbase;
			_vprogress = this["volcontrol"].vprogress;
			_vprogress.mouseEnabled = false;
			_normalscreen = this["normal"];
			_vframe = this["vframe"];
			_baseFrame = this["base_frame"];
			_vframe.alpha = _vframe.scaleY = 0;
			_volcontrol = this["volcontrol"];
			_volscrubber.buttonMode = true;
			_volcontrol.mouseChildren = _volcontrol.mouseEnabled = false;
			_volcontrol.alpha = 0;
		}
		private function initializeElements():void {
			_fullscreen.buttonMode = _normalscreen.buttonMode = true;
			_volume.buttonMode = true;
			_playButton.buttonMode = _pauseButton.buttonMode = true;
			_loadBar.scaleX = 0;
			_playBar.scaleX = 0;
			_pauseButton.alpha = _normalscreen.alpha = 0;
			_pauseButton.visible = _normalscreen.visible = false;
			_scrubber.buttonMode = true;
			_scrubber.addEventListener(MouseEvent.MOUSE_DOWN, onScrubberDown);
			_playButton.addEventListener(MouseEvent.CLICK, onPlayClick);
			_pauseButton.addEventListener(MouseEvent.CLICK, onPauseClick);
			
			_timeText.mouseEnabled = false;
			_loadBar.mouseEnabled = _playBar.mouseEnabled = false;
			_baseBar.addEventListener(MouseEvent.CLICK, onBaseBarClick);	
			_fullscreen.visible = _normalscreen.visible = _hasfullscreen;
			_normalscreen.alpha = 0;
			_volume.visible = _vframe.visible = _volcontrol.visible = _hasvolume;
			_volscrubber.addEventListener(MouseEvent.MOUSE_DOWN, onVolScrubberDown);
			_volscrubber.useHandCursor = _volscrubber.buttonMode = true;
			_normalscreen.mouseChildren = _normalscreen.mouseEnabled = false;
			_fullscreen.addEventListener(MouseEvent.CLICK, onFullscreenClick);
			_normalscreen.addEventListener(MouseEvent.CLICK, onFullscreenClick);
			
			if (!_autoHideVolume && _hasvolume) {
				_volcontrol.visible = _vframe.visible = true;
				_volcontrol.alpha = _vframe.alpha = 1;
				_volcontrol.mouseChildren = _volcontrol.mouseEnabled = true;
				_vframe.scaleY = 1;
				_volscrubber.addEventListener(MouseEvent.MOUSE_DOWN, onVolScrubberDown);
				_volscrubber.useHandCursor = _volscrubber.buttonMode = true;
			}else {
				_volume.addEventListener(MouseEvent.CLICK, onVolumeRollOver);
				_volume.useHandCursor = _volume.buttonMode = true;
			}
			activateAutoHideControls(_autoHideControls);
			
			
		}
		private function onFullscreenClick(evt:MouseEvent):void {
			
			dispatchEvent(new Event("onFullScreen"));
		}
		private function convertTime(t:Number):String {

			var retstring:String = "";
			
			var secs:Number = Math.floor(t) % 60;
			var min:Number = Math.floor(t / 60) % 60;
			if (isNaN(secs) || isNaN(min)) return "--:--";
			var ss:String = secs < 10 ? "0" + secs : secs.toString();
			var mm:String = min < 10 ? "0" + min : min.toString();
			return mm + ":" + ss;
		}
		private function onStreamCuePoint(evt:NetStreamManagerEvent):void{
		}
		private function applyTime(n1:Number, n2:Number):void {
			_timeText.text = convertTime(n1) + " / " + convertTime(n2);
		}
		private function onNetStatus(evt:NetStreamManagerEvent):void {
			trace(evt.data.code);
			if (evt.data.code == "NetStream.Play.Start") {
				
				_vprogress.scaleY = _ns.volume;
				updateVolume();
				hideElement(_playButton);
				showElement(_pauseButton);
			}
			if (evt.data.code == "NetStream.Play.Start" || 
				evt.data.code == "NetStream.Unpause.Notify" || 
				evt.data.code == "NetStream.Buffer.Full") {
				hideElement(_playButton);
				showElement(_pauseButton);
			}
			if (evt.data.code == "NetStream.Buffer.Empty" || 
				evt.data.code == "NetStream.Play.Stop" || 
				evt.data.code == "NetStream.Play.Failed" || 
				evt.data.code == "NetStream.Pause.Notify" || 
				evt.data.code == "NetStream.Play.Stop") {
					
					hideElement(_pauseButton);
					showElement(_playButton);
				}
		}

		private function onStreamMetaData(evt:NetStreamManagerEvent):void {
			_max = evt.data.duration;
			applyTime(0, evt.data.duration);
		}
		private function onStreamLoadProgress(evt:NetStreamManagerEvent):void {
			TweenLite.to(_loadBar, .6, { scaleX:evt.data.percent, ease:Strong.easeOut } );
		}
		private function onStreamLoadComplete(evt:NetStreamManagerEvent):void {
			TweenLite.to(_loadBar, .6, { scaleX:1, ease:Strong.easeOut } );
		}
		private function onStreamPlayProgress(evt:NetStreamManagerEvent):void {
			
			enabled = true;
			applyTime(evt.data.position, evt.data.total);
			TweenLite.to(_playBar, .6, { scaleX:evt.data.percent >= 0 ? evt.data.percent : 0, ease:Strong.easeOut, onUpdate:updateScrubber } );
		}
		private function onStreamPlayComplete(evt:NetStreamManagerEvent):void {
			_playcompleted = true;
			TweenLite.to(_playBar, .6, { scaleX:1, ease:Strong.easeOut, onUpdate:updateScrubber } );
		}
		private function updateScrubber() {
			if(!_scrubbing){
				_scrubber.x = Math.ceil(_playBar.x + _playBar.width);
			}
		}
		private function onYTLoadProgress(evt:YTPlayerEvent):void {
			if(!isNaN(evt.totalLoad)){
				TweenLite.to(_loadBar, .6, { scaleX:evt.totalLoad, ease:Strong.easeOut } );
			}
		}
		private function onYTBuffer(evt:YTPlayerEvent):void {
			_timeText.text = "buffering...";
		}
		private function onYTIdle(evt:YTPlayerEvent):void {
			_timeText.text = "buffering...";
			
			enabled = false;
		}
		private function onYTPlaying(evt:YTPlayerEvent):void {
			applyTime(evt.elapsedTime, evt.duration);
			TweenLite.to(_playBar, .6, { scaleX:evt.percentPlayed, ease:Strong.easeOut, onUpdate:updateScrubber } );
			hideElement(_playButton);
			showElement(_pauseButton);
		}
		private function onYTStarted(evt:YTPlayerEvent):void {
			_max = evt.duration;
			applyTime(0, _max);
			_vprogress.scaleY = _ytstream.volume;
			updateVolume();
			enabled = true;
			
		}
		private function onYTPaused(evt:YTPlayerEvent):void {
			hideElement(_pauseButton);
			showElement(_playButton);
		}
		public function displayPause():void{
			hideElement(_pauseButton);
			showElement(_playButton);
		}
		public function displayResume():void{
			showElement(_pauseButton);
			hideElement(_playButton);
		}
		private function onYTQueued(evt:YTPlayerEvent):void {
			
		}
		private function onYTCompleted(evt:YTPlayerEvent):void {
			
		}
		private function onYTLoading(evt:YTPlayerEvent):void {
			enabled = false;
			TweenLite.to(_playBar, .6, { scaleX:0, ease:Strong.easeOut, onUpdate:updateScrubber } );
			TweenLite.to(_loadBar, .6, { scaleX:0, ease:Strong.easeOut } );
		}
		private function clearChromelessEvents():void {
			ytstream.removeEventListener(YTPlayerEvent.BUFFERING, onYTBuffer);
			ytstream.removeEventListener(YTPlayerEvent.IDLE, onYTIdle);
			ytstream.removeEventListener(YTPlayerEvent.STARTED, onYTStarted);
			ytstream.removeEventListener(YTPlayerEvent.COMPLETED, onYTCompleted);
			ytstream.removeEventListener(YTPlayerEvent.PAUSED, onYTPaused);
			ytstream.removeEventListener(YTPlayerEvent.QUEUED, onYTQueued);
			ytstream.removeEventListener(YTPlayerEvent.PLAYING, onYTPlaying);
			ytstream.removeEventListener(YTPlayerEvent.LOADING, onYTLoading);
		}
		private function listenToChromeless():void {
			
			ytstream.addEventListener(YTPlayerEvent.BUFFERING, onYTBuffer);
			ytstream.addEventListener(YTPlayerEvent.IDLE, onYTIdle);
			ytstream.addEventListener(YTPlayerEvent.STARTED, onYTStarted);
			ytstream.addEventListener(YTPlayerEvent.COMPLETED, onYTCompleted);
			ytstream.addEventListener(YTPlayerEvent.PAUSED, onYTPaused);
			ytstream.addEventListener(YTPlayerEvent.QUEUED, onYTQueued);
			ytstream.addEventListener(YTPlayerEvent.PLAYING, onYTPlaying);
			ytstream.addEventListener(YTPlayerEvent.LOADING, onYTLoading);
		}
		private function clearStreamListeners():void {

			if (_ytchromeless) {
				clearChromelessEvents();
				return;
			}
			_ns.removeEventListener(NetStreamManagerEvent.ON_CUEPOINT, onStreamCuePoint);
			_ns.removeEventListener(NetStreamManagerEvent.LOAD_PROGRESS, onStreamLoadProgress);
			_ns.removeEventListener(NetStreamManagerEvent.LOAD_COMPLETE, onStreamLoadComplete);
			_ns.removeEventListener(NetStreamManagerEvent.PLAY_PROGRESS, onStreamPlayProgress);
			_ns.removeEventListener(NetStreamManagerEvent.PLAY_COMPLETE, onStreamPlayComplete);
			_ns.removeEventListener(NetStreamManagerEvent.META_DATA, onStreamMetaData);
			_ns.removeEventListener(NetStreamManagerEvent.STATUS, onNetStatus);
		}
		private function listenToStream():void {
			if (_ytchromeless) {
				listenToChromeless();
				return;
			}
			_ns.addEventListener(NetStreamManagerEvent.ON_CUEPOINT, onStreamCuePoint);
			_ns.addEventListener(NetStreamManagerEvent.LOAD_PROGRESS, onStreamLoadProgress);
			_ns.addEventListener(NetStreamManagerEvent.LOAD_COMPLETE, onStreamLoadComplete);
			_ns.addEventListener(NetStreamManagerEvent.PLAY_PROGRESS, onStreamPlayProgress);
			_ns.addEventListener(NetStreamManagerEvent.PLAY_COMPLETE, onStreamPlayComplete);
			_ns.addEventListener(NetStreamManagerEvent.META_DATA, onStreamMetaData);
			_ns.addEventListener(NetStreamManagerEvent.STATUS, onNetStatus);
		}
		private function onBaseBarClick(evt:MouseEvent):void {
			if (_ns || _ytstream) {
				_ytchromeless ? _ytstream.pauseVideo() : _ns.pause();
				TweenMax.to(_scrubber, .1, { x:_baseBar.x + _baseBar.mouseX, ease:Strong.easeOut,  onComplete:baseBarAnimateComplete } );
			}
		}
		private function baseBarAnimateComplete():void {
			updatePlayBar();
			_ytchromeless ? _ytstream.playVideo() : _ns.play();
		}
		
		private function updateVolume():void {
			
			_volscrubber.y = -_vprogress.height;
		}
		private function updateVolumeProgress(evt:MouseEvent):void {
			_vprogress.height = _volscrubber.y * -1;
			if (_ytchromeless) {
				_ytstream.volume = _vprogress.scaleY;
			}else{
				_ns.volume = _vprogress.scaleY;
			}
		}
		private function onPlayClick(evt:MouseEvent):void {
			_ytchromeless ? _ytstream.playVideo() : _ns.play();
			hideElement(_playButton);
			showElement(_pauseButton);
		}
		private function onPauseClick(evt:MouseEvent):void {
			
			_ytchromeless ? _ytstream.pauseVideo() : _ns.pause();
			hideElement(_pauseButton);
			showElement(_playButton);
		}
		private function checkVolumeRolls():void {
			
			if (!_vframe.hitTestPoint(stage.mouseX, stage.mouseY, true)) {
				TweenMax.to(_volcontrol, .5, { alpha:0, ease:Strong.easeInOut } );
				TweenMax.to(_vframe, 1, {alpha:0, scaleY:0, ease:Strong.easeInOut } );
				_volcontrol.mouseEnabled = _volcontrol.mouseChildren = false;
				_volume.useHandCursor = _volume.buttonMode = true;
				_volume.addEventListener(MouseEvent.CLICK, onVolumeRollOver);	
				activateAutoHideControls(_autoHideControls);
				
				
			}else {
				setTimeout(checkVolumeRolls, 1000);
			}
		}
		private function onVolumeRollOver(evt:MouseEvent):void {
			TweenMax.to(_volcontrol, .5, { delay:.5, alpha:1, ease:Strong.easeInOut } );
			TweenMax.to(_vframe, 1, {alpha:1, scaleY:1.05, ease:Strong.easeInOut } );
			_volcontrol.mouseEnabled = _volcontrol.mouseChildren = true;
			_volume.removeEventListener(MouseEvent.CLICK, onVolumeRollOver);
			activateAutoHideControls(false);
			setTimeout(checkVolumeRolls, 1000);
		}
		private function onScrubberUp(evt:MouseEvent):void {
			
			if(_ytchromeless){
				_ytstream.seek(_playBar.scaleX * _max);
			}
			_scrubbing = false;
			_ytchromeless ? _ytstream.playVideo() : _ns.play();
			try{
				_ns.addEventListener(NetStreamManagerEvent.PLAY_PROGRESS, onStreamPlayProgress);
			}catch(e:Error){}
			_scrubber.stopDrag();
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, dragScrubber);
			_scrubber.removeEventListener(MouseEvent.MOUSE_UP, onScrubberUp);
			stage.removeEventListener(MouseEvent.MOUSE_UP, onScrubberUp);
		}
		private function updatePlayBar():void {
			_playBar.width = _scrubber.x - _baseBar.x;
			try{
				_ns.seek(_playBar.scaleX * _max);
			}catch(e:Error){}
			applyTime(_playBar.scaleX * _max, _max);
		}
		private function dragScrubber(evt:MouseEvent):void {
			if(mouseX < _baseBar.x+_baseBar.width && mouseX >_baseBar.x){
				_scrubber.x = mouseX;
			}
			if (_scrubber.x < _baseBar.x) {
				_scrubber.x = _baseBar.x;
			}
			if (_scrubber.x > _baseBar.x + _baseBar.width) {
				_scrubber.x = Math.floor(_baseBar.x + _baseBar.width);
			}
			updatePlayBar();
		}
		private function onScrubberDown(evt:MouseEvent):void {
			TweenMax.killTweensOf(_playBar);
			_scrubbing = true;
			_ytchromeless ? _ytstream.pauseVideo() : _ns.pause();
			try{
				_ns.removeEventListener(NetStreamManagerEvent.PLAY_PROGRESS, onStreamPlayProgress);
			}catch(e:Error){}
			var dy:Number = Math.floor(_scrubber.y);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, dragScrubber);
			_scrubber.addEventListener(MouseEvent.MOUSE_UP, onScrubberUp);
			stage.addEventListener(MouseEvent.MOUSE_UP, onScrubberUp);
			
		}
		private function onVolScrubberUp(evt:MouseEvent):void {
			_volscrubber.stopDrag();
			
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, updateVolumeProgress);
			_scrubber.removeEventListener(MouseEvent.MOUSE_UP, onVolScrubberUp);
			stage.removeEventListener(MouseEvent.MOUSE_UP, onVolScrubberUp);
		}
		private function onVolScrubberDown(evt:MouseEvent):void {
			
			_volscrubber.startDrag(false, new Rectangle(_vbase.x, _vbase.y, _vbase.x, -_vbase.height));
			stage.addEventListener(MouseEvent.MOUSE_MOVE, updateVolumeProgress);
			_scrubber.addEventListener(MouseEvent.MOUSE_UP, onVolScrubberUp);
			stage.addEventListener(MouseEvent.MOUSE_UP, onVolScrubberUp);
		}
		
		private function hideElement(targ:MovieClip):void {
			if (targ.alpha > 0) {
				targ.mouseEnabled = false;
				TweenMax.killTweensOf(targ);
				TweenMax.to(targ, .6, { autoAlpha:0, ease:Strong.easeOut } );
			}
		}
		private function showElement(targ:MovieClip):void {
			if (targ.alpha < 1) {
				targ.mouseEnabled = true;
				TweenMax.killTweensOf(targ);
				TweenMax.to(targ, .6, { autoAlpha:1, ease:Strong.easeOut } );
			}
		}
		public function onAutoPlayFalse():void {
			hideElement(_pauseButton);
			showElement(_playButton);
		}
		private function activateAutoHideControls(b:Boolean):void {
			if (b) {
				_fstimer.start();
				stage.addEventListener(MouseEvent.MOUSE_MOVE, resetHideTimer);
			}else {
				stage.removeEventListener(MouseEvent.MOUSE_MOVE, resetHideTimer);
				_fstimer.stop();
				if (_hidden) {
					showMe();
				}
			}
		}
		public function set stream(ns:NetStreamManager):void {
			_ns = ns;
			clearStreamListeners();
			listenToStream();
		}
		public function set hasVolume(b:Boolean):void {
			_hasvolume = b;
		}
		public function set hasFullscreen(b:Boolean):void {
			_hasfullscreen = b;
		}
		public function get stream():NetStreamManager {
			return _ns;
		}
		public function set ytstream(yt:YTChromelessPlayer):void {
			_ytstream = yt;
			listenToStream();
		}
		public function get ytstream():YTChromelessPlayer {
			return _ytstream;
		}
		public function set ytchromeless(b:Boolean):void {
			_ytchromeless = b;
		}
		public function get ytchromeless():Boolean {
			return _ytchromeless;
		}
		public function set autoHideVolume(b:Boolean):void{
			_autoHideVolume = b;
		}
		public function set autoHideControls(b:Boolean):void {
			_autoHideControls = b;
			
		}
		public function get autoHideControls():Boolean {
			return _autoHideControls;
		}
		override public function get enabled():Boolean { 
			return mouseEnabled && mouseChildren; 
		}
		override public function set enabled(value:Boolean):void {
			mouseEnabled = mouseChildren = value;
		}
		public function get autoHideVolume():Boolean {
			return _autoHideVolume;
		}
		override public function get height():Number {
			if(_baseFrame){
				return _baseFrame.height;
			}
			return defControlHeight || 0; 
		}
		public function set isFullScreen(b:Boolean):void {
			if (b) {
				stage.addEventListener(MouseEvent.MOUSE_MOVE, resetHideTimer);
				_normalscreen.mouseChildren = _normalscreen.mouseEnabled = true;
				_normalscreen.useHandCursor = _normalscreen.buttonMode = true;
				_normalscreen.alpha = 1
				_fullscreen.alpha = 0;
				_fullscreen.mouseChildren = _fullscreen.mouseEnabled = false;
				_fstimer.start();
			}else {
				stage.removeEventListener(MouseEvent.MOUSE_MOVE, resetHideTimer);
				_normalscreen.mouseChildren = _normalscreen.mouseEnabled = false;
				_normalscreen.alpha = 0;
				_fullscreen.alpha = 1;
				_fullscreen.useHandCursor = _fullscreen.buttonMode = true;
				_fullscreen.mouseChildren = _fullscreen.mouseEnabled = true;
				_fstimer.stop();
				if (_hidden) {
					showMe();
				}
			}
		}
		public function seekTo(sec:Number):void {
			
			_playBar.scaleX = sec / _max;
			trace(_playBar.scaleX * _max);
			(_ytchromeless) ? _ytstream.seek(_playBar.scaleX * _max) : _ns.seek(_playBar.scaleX * _max);
			_ytchromeless ? _ytstream.playVideo() : _ns.play();
			applyTime(_playBar.scaleX * _max, _max);
		}
		
		
	}
	
}